package com.gitee.es.dynamics.aop;

import com.gitee.es.dynamics.annotation.Des;
import com.gitee.es.dynamics.common.Const;
import com.gitee.es.dynamics.common.LocalCache;
import com.gitee.es.dynamics.config.ThreadLocalConfig;
import com.gitee.es.dynamics.exception.DynamicsElasticSearchException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


@Aspect
public class ElasticSearchAspect {
    /**
     * 拦截子类方法
     *
     * @return void
     * @date 2023/12/25 15:57
     * @author glq
     */
    @Pointcut("within(com.gitee.es.dynamics.service.impl.ElasticSearchServiceImpl+)")
    public void servicePointCut() {
    }

    /**
     * 拦截ElasticsearchRestTemplate执行
     *
     * @return void
     * @date 2023/12/25 15:57
     * @author glq
     */
    @Pointcut("target(org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate)")
    public void templatePointCut() {
    }


    /**
     * 拦截子类环绕通知
     *
     * @param joinPoint 代理对象
     * @return java.lang.Object
     * @date 2023/3/6 15:21
     * @author glq
     */
    @Around("servicePointCut()")
    public Object serviceAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Class<?> tClass = joinPoint.getTarget().getClass();
        Des annotation = tClass.getAnnotation(Des.class);
        if (annotation != null) {
            if (Const.EMPTY_STR.equals(annotation.value().trim())) {
                throw new DynamicsElasticSearchException("value can't be empty!");
            } else {
                ThreadLocalConfig.set(Const.BEAN_PREFIX1 + annotation.value());
            }
        }
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Des des = signature.getMethod().getAnnotation(Des.class);
        if (des != null) {
            if (Const.EMPTY_STR.equals(des.value().trim())) {
                throw new DynamicsElasticSearchException("value can't be empty!");
            } else {
                ThreadLocalConfig.set(Const.BEAN_PREFIX1 + des.value());
            }
        }
        if (annotation == null && des == null) {
            ThreadLocalConfig.set(Const.BEAN_PREFIX1 + Const.DES);
        }
        Object proceed = joinPoint.proceed();
        ThreadLocalConfig.remove();
        return proceed;
    }

    /**
     * 拦截模板环绕通知
     *
     * @param joinPoint 代理对象
     * @return java.lang.Object
     * @date 2023/3/6 15:21
     * @author glq
     */
    @Around("templatePointCut()")
    public Object templateAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        if (ThreadLocalConfig.get() == null) {
            return method.invoke(LocalCache.get(Const.BEAN_PREFIX1 + Const.DES), joinPoint.getArgs());
        } else {
            return method.invoke(LocalCache.get(ThreadLocalConfig.get()), joinPoint.getArgs());
        }
    }
}
